<?php
declare (strict_types=1);

namespace app\controller;

use app\common\ApplePay;
use app\common\UsersService;
use app\job\Task;
use app\model\Message;
use app\model\Point;
use app\model\TalentGoodsOrders;
use app\model\TalentGoodsOrdersRenew;
use app\model\Users;
use app\model\UsersOrder;
use app\model\Vip;
use app\Request;
use think\Exception;
use think\facade\Log;
use think\facade\Queue;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;
use Yansongda\Pay\Pay;

class CallbackController
{
	
	
	function Notify(Request $request)
	{
		Log::record('支付回调');
		try {
			$paytype = $request->param('paytype');
			$scene = $request->param('scene');
	
			if (!in_array($scene, ['global', 'china'])) {
				throw new Exception('支付场景错误');
			}
			if (in_array($paytype, ['wechat', 'alipay'])) {
				$config = config('pay');
				if ($paytype == 'wechat') {
					if ($scene == 'china') {
						Log::record('微信中国支付');
						$pay = Pay::wechat($config);
						try {
							$res = $pay->callback();
						} catch (\Exception $e) {
							throw new Exception('验签错误');
						}
						Log::record('验签通过');
						$res = $res->resource;
						Log::record('返回值');
						Log::record($res);
						$res = $res['ciphertext'];
						$out_trade_no = $res['out_trade_no'];
						$attach = $res['attach'];
					} else {
						$inWechatpaySignature = request()->header('Wechatpay-Signature');
						$inWechatpayTimestamp = request()->header('Wechatpay-Timestamp');
						$inWechatpayNonce = request()->header('Wechatpay-Nonce');
						$inBody = file_get_contents('php://input');
						// 根据通知的平台证书序列号，查询本地平台证书文件，
						$platformCertificateFilePath = file_get_contents('cert/633D73FFFDFA22C9CEF8BF35922024A443CCA851.crt');
						$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
						// 检查通知时间偏移量，允许5分钟之内的偏移
						$timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
						$verifiedStatus = Rsa::verify(
						// 构造验签名串
							Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
							$inWechatpaySignature,
							$platformPublicKeyInstance
						);
						if (!$timeOffsetStatus && !$verifiedStatus) {
							throw new Exception('签名构造错误或超时');
						}
						// 转换通知的JSON文本消息为PHP Array数组
						$inBodyArray = json_decode($inBody, true);
						// 使用PHP7的数据解构语法，从Array中解构并赋值变量
						['resource' => [
							'ciphertext' => $ciphertext,
							'nonce' => $nonce,
							'associated_data' => $aad
						]] = $inBodyArray;
						// 加密文本消息解密
						$inBodyResource = AesGcm::decrypt($ciphertext, 'a123456789b123456789c123456789d1', $nonce, $aad);
						// 把解密后的文本转换为PHP Array数组
						$inBodyResourceArray = json_decode($inBodyResource, true);
						if ($inBodyResourceArray['trade_state'] != 'SUCCESS' || $inBodyResourceArray['trade_state_desc'] != '支付成功') {
							throw new Exception('支付失败');
						}
						$out_trade_no = $inBodyResourceArray['out_trade_no'];
						$attach = $inBodyResourceArray['attach'];
					}
				} else {
					if ($scene == 'china') {
						$pay = Pay::alipay($config);
						$res = $pay->callback();
						$out_trade_no = $res->out_trade_no;
						$attach = $res->passback_params;
					} else {
						throw new Exception('暂未开放支付宝国际支付');
					}
				}
			} elseif ($paytype == 'apple') {
				if ($scene == 'china') {
					throw new Exception('暂未开放苹果国内支付');
				}else{
					$receipt = $request->param('receipt');
					ApplePay::verifyReceipt($receipt);
					$out_trade_no = $request->param('order_sn');
					$attach = $request->param('attach');
				}
			
			} else {
				throw new Exception('支付方式错误');
			}
			switch ($attach) {
				case 'vip_pay':
					$orders = UsersOrder::where(['order_sn' => $out_trade_no, 'type' => 'vip', 'pay_status' => 0])->find();
					if (!$orders) {
						throw new Exception('空数据');
					}
					$orders->pay_status = 1;
					$orders->save();
					$vip = Vip::findOrFail($orders->pro_id);
					$users = Users::findOrFail($orders->users_id);
					$users->gpt_num += $vip->gpt_num;
					$users->save();
					break;
				case 'point_pay':
					$orders = UsersOrder::where(['order_sn' => $out_trade_no, 'type' => 'point', 'pay_status' => 0])->find();
					if (!$orders) {
						throw new Exception('空数据');
					}
					$orders->pay_status = 1;
					$orders->save();
					$point = Point::findOrFail($orders->pro_id);
					
					//变更积分
					UsersService::changeScore($point->num, $orders->users_id, '充值积分');
					break;
				case 'talent_goods_pay':
					Log::record('专业团队支付');
					Log::record('专业团队支付');
					$orders = TalentGoodsOrders::where(['order_sn' => $out_trade_no, 'pay_status' => 0])->find();
					if (!$orders) {
						throw new Exception('空数据');
					}
					$orders->pay_status = 3;
					$orders->paytime = time();
					$orders->save();
					//支付成功发邮件通知雇主
					Queue::push(Task::class, ['data' => ['id' => $orders->id], 'action' => 'TalentGoodSendMail'], 'task');
					break;
				case 'talent_goods_renew':
					$orders = TalentGoodsOrdersRenew::where(['order_sn' => $out_trade_no, 'status' => 0])->find();
					if (!$orders) {
						throw new Exception('空数据');
					}
					$orders->status = 1;
					$orderInfo = $orders->orders;
					$sku = $orderInfo->sku_json;
					$minutes = $sku['minutes'];
					$expiretime = $minutes * 60;
					Queue::later($expiretime, Task::class, ['data' => ['id' => $orderInfo->id], 'action' => 'TalentGoodsServiceOver'], 'task'); //增加延迟队列
					$orders->orders->pay_status = 1; //修正状态
					$orders->orders->expiretime += $expiretime; //修正过期时间
					$orders->together(['orders'])->save();
					break;
			}
			
			if (in_array($paytype, ['wechat', 'alipay'])) {
				if ($scene == 'china') {
					return $pay->success();
				} else {
					exit('success');
				}
			} else {
				writeJson();
			}
		}catch (\Throwable $e){
			Log::record("支付回调错误");
			Log::record($e->getMessage());
			writeJson(0,$e->getMessage());
		}
		
	}
	
	function tencent_im(Request $request)
	{
		$params = $request->all();
		$UsesrModel = new Users();
		if ($params['CallbackCommand'] == 'State.StateChange') {
			if ($params['Info']['Action'] == 'Login') {
				$UsesrModel->where('id', $params['Info']['To_Account'])->update(['online' => 1]);
			}
			if ($params['Info']['Action'] == 'Disconnect') {
				$UsesrModel->where('id', $params['Info']['To_Account'])->update(['online' => 0]);
			}
		}
		if ($params['CallbackCommand'] == 'C2C.CallbackAfterSendMsg' && $params['SendMsgResult'] == 0) {
			$row = Message::where(['from_users_id' => $params['From_Account'], 'to_users_id' => $params['To_Account']])->whereTime('createtime', 'day')->find();
			if (!$row) {
				Message::create(['from_users_id' => $params['From_Account'], 'to_users_id' => $params['To_Account']]);
			}
		}
	}
	
	
}
